Domain patterns for CLI tools and developer SDKs — command structure, configuration layering, plugin architecture, distribution, backward compatibility, shell integration, and failure modes. Use when designing or evaluating command-line tools, developer platforms, or SDK libraries.
复制安装指令,让 AI 自动完成配置 · 推荐新手
请帮我安装 askskill 上的 "system-type-cli-tool" 技能: 1. 下载 https://raw.githubusercontent.com/microsoft/amplifier-bundle-systems-design/main/skills/system-type-cli-tool/SKILL.md 2. 保存为 ~/.claude/skills/system-type-cli-tool/SKILL.md 3. 装好后重载技能,告诉我可以用了
Patterns, failure modes, and anti-patterns for command-line tools and developer-facing libraries.
What it is. Top-level command dispatches to subcommands, each with its own flags and arguments. tool <subcommand> [flags] [args]. The dominant pattern for non-trivial CLIs.
When to use. Tools with more than ~5 distinct operations. When operations have different flag sets. When you want discoverability — tool help lists all subcommands.
When to avoid. Single-purpose tools that do one thing (e.g., curl, jq). Adding subcommands to a tool that does one thing well makes it do many things poorly.
Nesting depth. Two levels (tool resource action) is the practical limit. Three levels (tool group resource action) works if the grouping is obvious (e.g., kubectl get pods). Four levels means your CLI needs a redesign.
POSIX short flags. Single dash, single letter: -v, -f. Combinable: -vvv for verbosity levels, -rf for multiple flags. Every short flag should have a long equivalent.
GNU long flags. Double dash, full words: --verbose, --output-format. Self-documenting. Use hyphens, not underscores.
Boolean flags. --color enables, --no-color disables. Pick a sensible default and provide the negation. Don't require --color=true.
Value flags. --output json or --output=json. Support both forms. Be consistent across all flags.
The -- separator. Everything after -- is a positional argument, not a flag. Mandatory for tools that accept arbitrary user input — without it, tool delete --force is ambiguous (is --force a flag or an argument?).
Positional args are for the primary noun — the thing being operated on. tool build ./src, tool deploy production. One or two positional args maximum. After that, you need flags.
Flags are for everything that modifies behavior. If the user could reasonably forget to provide it and get a useful default, it's a flag, not a positional arg.
Rule of thumb. If you're reading the help text to remember which positional arg is which, they should be flags.
Global flags apply to every subcommand: --verbose, --config, --output-format, --no-color. Define them once at the root. They should be few and genuinely universal.
Local flags belong to a specific subcommand. Don't pollute the global namespace with flags only one subcommand uses.
Interactive prompts are for first-run setup, destructive confirmations, and guided workflows (tool init). Always provide a flag equivalent (--yes, --name=foo) so scripts can bypass prompts.
TTY detection. If stdin is not a TTY, never prompt. Fail with an actionable error telling the user which flag to pass. A CI pipeline hanging on a prompt is a production incident.
stdout is for program output — the data the user asked for. It must be parseable. If someone pipes your output, only the data should flow through.
stderr is for human messages — progress indicators, warnings, debug info, error messages. Everything that isn't the requested data.
stdin is for data input. Accept - as a filename to mean stdin. Support piping: cat file | tool process and tool process < file.
The test. tool list | wc -l should return a correct count. If your progress spinner or status message contaminates stdout, you've broken the Unix contract.
Highest precedence wins. The standard order:
TOOLNAME_FLAGNAME (e.g., GIT_AUTHOR_NAME).…
Catalog of reusable architectural primitives — boundaries, contracts, state machines, queues, caches, consistency models, and more. For each: what it is, when it's right, when it's WRONG. Use when selecting patterns for a design or evaluating whether a pattern fits.
Domain-Driven Design as a lens for system architecture — bounded contexts, aggregates, ubiquitous language, context mapping, domain events, and strategic vs tactical patterns. Use when modeling complex business domains, defining service boundaries, or evaluating whether a system's structure reflects its domain.
The Unix/Linux design philosophy as a lens for system design — mechanism vs policy, composability, small tools, text streams, convention over configuration, and the principle of least surprise. Use when evaluating designs for composability, simplicity, or separation of concerns.
Object-oriented design principles as a lens for system architecture — SOLID, composition over inheritance, the actor model, design patterns (and when they're wrong), encapsulation, polymorphism, and responsibility-driven design. Use when evaluating code organization, module boundaries, or object/component relationships.
Domain patterns for Azure cloud architecture — compute selection, managed services, identity (Entra ID), networking, data platform, messaging, deployment, cost management, and operational patterns. Use when designing or evaluating a system deployed on Microsoft Azure.
Adversarial review of a system design from 6 critical perspectives -- SRE, security, staff engineer, finance, operator, and developer advocate. Produces a unified risk assessment. Use for INTERACTIVE on-demand reviews during a design conversation (/adversarial-review). For RECIPE-DRIVEN reviews (where prior step context is needed), use the systems-design-critic agent instead.